package com.stockz.ui.swing.charting.display.indicator;

import java.awt.Graphics2D;
import java.util.List;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.stockz.core.model.Bar;
import com.stockz.core.util.ListUtil;
import com.stockz.ui.swing.charting.painter.indicator.LineIndicatorPainter;
import com.stockz.ui.swing.charting.util.UIChartingConstant.OVERLAY;

@Component
@Scope("prototype")
public class BollingerBands extends
		AbstractDisplayableIndicatorConfiguration{
	public static class Configuration{
		private int span = 20;
		private double multiple = 2;
		private boolean modified = false;
		private boolean exponencial = false;
		
		public int getSpan() {
			return span;
		}
		public void setSpan(int span) {
			this.span = span;
		}
		public double getMultiple() {
			return multiple;
		}
		public void setMultiple(double multiple) {
			this.multiple = multiple;
		}
		public boolean isModified() {
			return modified;
		}
		public void setModified(boolean modified) {
			this.modified = modified;
		}
		public boolean isExponencial() {
			return exponencial;
		}
		public void setExponencial(boolean exponencial) {
			this.exponencial = exponencial;
		}
	}
	
	
	public static double[] value(double[] barValues, int span, double mult,
			boolean modified, boolean exponencial){
		if(barValues != null){
			
		}
		return new double[0];
	}
	
	public static double[][] values(double[] barValues, int span, double mult,
			boolean modified, boolean exponencial){
		if(barValues != null){
			double[][] values = new double[3][barValues.length];
			double sum = 0; 
			double sumSquared = 0;
			if(barValues.length > 0 && span > 1 && span <= barValues.length){
				for(int i = barValues.length-1; i >=0; i--){
					if(barValues[i] == 0){
						continue;
					}
					if(i > barValues.length - span){
						
					}else if(i ==  barValues.length - span){
						values[1][i] = sum/span;
						double stdDev = Math.sqrt((span * sumSquared - (sum * sum))/ (span * (span- 1)));
						values[0][i] = values[1][i] + mult*stdDev;
						values[2][i] = values[1][i] - mult*stdDev;
					}else{
						values[1][i] = sum/span;
						double stdDev = Math.sqrt((span * sumSquared - (sum * sum))/ (span * (span- 1)));
						values[0][i] = values[1][i] + mult*stdDev;
						values[2][i] = values[1][i] - mult*stdDev;
						
						sum -= barValues[i+span];
						sumSquared -= (barValues[i+span]*barValues[i+span]);
					}
					sum += barValues[i];
					sumSquared += (barValues[i]*barValues[i]);
				}
			}
			return values;
		}
		return new double[0][0];
	}
	
	private Configuration configuration = new Configuration();
	private double[][] values;
	
	@Override
	public String getFullName() {
		return "Bollinger Bands";
	}

	@Override
	public String getShortName() {
		return "BB";
	}

	@Override
	public String getDescription() {
		return getFullName()+","+configuration.getSpan()+","+configuration.getMultiple()+", "+getBarValueType();
	}

	@Override
	public OVERLAY getOverlay() {
		return OVERLAY.PRICE;
	}

	@Override
	public boolean isOverlappable() {
		return true;
	}

	@Override
	public void paint(Graphics2D g) {
		for(int i = 0; i < values.length; i++){
			LineIndicatorPainter.paint(g, this, values[i]);
		}
	}

	@Override
	public void refreshValues() {
		List<Bar> barList = getStockChartPanel().getStockChartPanelState().getBarList();
		if(barList != null && barList.size() > configuration.getSpan()){
			double[] barValues = ListUtil.convert(barList, getBarValueType());
			values = BollingerBands.values(barValues, configuration.getSpan(), 
					configuration.getMultiple(), configuration.isModified(), configuration.isExponencial());
		}
	}

	@Override
	public Object getConfiguration() {
		return configuration;
	}
}
